﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ufida.u9.ait.openapi.utils;
using UFIDA.U9.Base;
using UFIDA.U9.CBO.FI_SCM.DTOs;
using UFIDA.U9.CBO.HR.Department;
using UFIDA.U9.CBO.HR.Operator;
using UFIDA.U9.CBO.SCM.Enums;
using UFIDA.U9.CBO.SCM.Item;
using UFIDA.U9.CBO.SCM.Supplier;
using UFIDA.U9.CBO.SCM.Warehouse;
using UFIDA.U9.ISV.RCV.DTO;
using UFIDA.U9.ISV.RCV;
using UFIDA.U9.PM.ASN;
using UFIDA.U9.PM.Enums;
using UFIDA.U9.PM.PO;
using UFIDA.U9.PM.Pub;
using UFIDA.U9.PM.Rcv;
using UFSoft.UBF.Business;
using UFIDA.U9.CBO.FI.Tax;
using UFIDA.U9.Base.Currency;
using UFIDA.U9.FA.FA_AssetCardBE;
using UFIDA.U9.CBO.SCM.ProjectTask;

namespace ufida.u9.ait.openapi
{
    internal class RCVBase
    {
        

        /// <summary>
        /// 依据分发行建立固定资产卡片
        /// </summary>
        /// <param name="doc">收货单BE</param>
        /// <param name="dto">收货单DTO</param>
        public static List<AssetCard> RcvCreateCard(Receivement doc, CopyOfOBAReceivementDTOData dto)
        {
            U9Utils.ClearCache();
            doc = doc.Key.GetEntity();

            AssetCard assetCard = null;
            List<AssetCard> retlist = new List<AssetCard>();
            //缓存DTO行集合
            Dictionary<int, CopyOfOBARcvLineDTOData> linesdic= new Dictionary<int, CopyOfOBARcvLineDTOData>();
            foreach(var linedto in dto.RcvLines)
            {
                linesdic.Add(linedto.DocLineNo, linedto);
            }

            foreach(var line in doc.RcvLines)
            {
                if (line.RcvLineDispenses == null || line.RcvLineDispenses.Count == 0)
                    continue;
                CopyOfOBARcvLineDTOData linedto = linesdic[line.DocLineNo];
                if (linedto == null) throw new Exception("依据行号获取收货单行DTO失败");
                if (linedto.RcvLineDispenses == null || line.RcvLineDispenses.Count == 0)
                    continue;
                CopyOfOBARcvLineDispenseDTOData disdto = linedto.RcvLineDispenses[0];//收货分发行DTO

                foreach (var disline in line.RcvLineDispenses)
                {
                    //构造卡片数据
                    AssertCardAITDTOData data = new AssertCardAITDTOData();

                    //单号处理
                    if (!string.IsNullOrEmpty(disdto.CardNo))
                    {
                        data.DocNo = disdto.CardNo;
                    }
                    else
                    {
                        data.DocNo = doc.DocNo;
                    }

                    data.StartDate = doc.BusinessDate.ToString();
                    data.BusinessDate = doc.BusinessDate.ToString();
                    data.Qty = (int)disline.DispenseQtyTU;//数量
                    data.Item = new CopyOfCommonArchiveDataDTOData() { Code = line.ItemInfo.ItemCode };
                    //单据类型=采购收货到固定资产
                    data.DocumentType=new CopyOfCommonArchiveDataDTOData(){ Code = "01" };
                    if (disdto.UseDept == null) throw new Exception("收货分发DTO 使用部门为空");
                    data.UsageDept = disdto.UseDept;//使用部门
                    data.UsagePrincipal = disdto.UseMan;//使用人员
                    if (disdto.OwnerDept != null)
                    {
                        data.OwnerDept = new CopyOfCommonArchiveDataDTOData() { Code = disdto.OwnerDept.Code };//管理部门
                    }
                    else
                    {
                        data.OwnerDept = new CopyOfCommonArchiveDataDTOData() { Code = disdto.UseDept.Code };//管理部门
                    }
                    if (disdto.AuditDept != null)
                    {
                        data.AuditDept = new CopyOfCommonArchiveDataDTOData() { Code = disdto.AuditDept.Code };//核算部门
                    }
                    else
                    {
                        data.AuditDept = new CopyOfCommonArchiveDataDTOData() { Code = disdto.UseDept.Code };//核算部门
                    }
                    data.Owner = disdto.Owner;//责任人
                    
                    //资产类别
                    data.AssetCategory=disdto.AssetCategory;
                    //资产位置
                    data.AssetLocation=disdto.AssetLocation;
                    //来源单据
                    data.SourceDoc = new AssertCardSourceDocAITDTOData()
                    {
                        SourceDocCode = doc.DocNo,
                        SourceDocLineNo=line.DocLineNo,
                        SourceDocLineDetailNo=disline.DispenseLineNo,
                    };
                    //描述性弹性域
                    if (disdto.DescFlexSegments != null)
                    {
                        data.DescFlexField = new CopyOfDescFlexSegmentsData();
                        DTOUtils.DTOPropCopy(disdto.DescFlexSegments, data.DescFlexField);
                    }
                    if (disdto.TagDescFlexSegments != null)
                    {
                        data.TagDescFlexField = new CopyOfDescFlexSegmentsData();
                        DTOUtils.DTOPropCopy(disdto.TagDescFlexSegments, data.TagDescFlexField);
                    }
                    //项目
                    if (line.Project != null)
                    {
                        data.Project = new CopyOfCommonArchiveDataDTOData()
                        {
                            Code = line.Project.Code,
                        };
                    }
                    //其他字段
                    data.AssetDescription = disdto.AssetDescription;//资产描述

                    //创建卡片
                    assetCard = AssertCardBase.CreateDoc(data);
                    //修改单号
                    EntityUtils.UpdateDocNo<AssetCard>(assetCard.ID, data.DocNo);

                    //处理返回
                    assetCard = assetCard.Key.GetEntity();
                    retlist.Add(assetCard);
                }
                
            }

            

            return retlist;
        }

        /// <summary>
        /// 收货行分发
        /// </summary>
        /// <param name="linedto"></param>
        /// <param name="doc"></param>
        public static void RcvDispense(CopyOfOBARcvLineDTOData linedto, Receivement doc)
        {
            //不存在分发行,退出
            if (linedto.RcvLineDispenses == null || linedto.RcvLineDispenses.Count == 0)
                return;
            //依据DTO行号,获取实体行
            RcvLine line1 = null;
            foreach (var line in doc.RcvLines)
            {
                if (line.DocLineNo == linedto.DocLineNo)
                {
                    line1 = line;
                    break;
                }
            }
            if (line1 == null) throw new Exception("收货分发,依据行号获取行失败!");

            //创建参数DTO
            List<RcvLineDistributeLineDTO> dtos = new List<RcvLineDistributeLineDTO>();
            foreach (var dtodata in linedto.RcvLineDispenses)
            {
                RcvLineDistributeLineDTO dto = new RcvLineDistributeLineDTO();
                if (dtodata.UseDept == null) throw new Exception("分发 UseDept 必填");

                dto.UseDept = new UFIDA.U9.Base.DTOs.IDCodeNameDTO() { Code = dtodata.UseDept.Code };//领用部门
                if (dtodata.UseMan != null)
                {
                    dto.UseMan = new UFIDA.U9.Base.DTOs.IDCodeNameDTO() { Code = dtodata.UseMan.Code };//领用人
                }

                dto.DispenseQtyTU = dtodata.DispenseQtyTU;//分发数量1

                dto.UsedMnyTC = line1.FinallyPriceTC * dtodata.DispenseQtyTU;//含税领用额
                dto.UsedMnyTC = EntityUtils.GetRoundMny(doc.TC, dto.UsedMnyTC);//精度

                dto.NetUsedMnyTC = dto.UsedMnyTC / (1 + line1.TaxRate);//未税领用额
                dto.NetUsedMnyTC = EntityUtils.GetRoundMny(doc.TC, dto.NetUsedMnyTC);//精度

                dto.UsedTaxTC = dto.UsedMnyTC - dto.NetUsedMnyTC;//领用税额


                dto.NetFeeTC = 0;//未税应摊费用额
                dto.FeeTC = 0;//含税应摊费用额
                dto.FeeTaxTC = 0;//应摊费用税额

                dto.ActionType = BusinessOperatorTypeEnum.NewCreate;//默认新增
                dtos.Add(dto);
            }

            //调用BP
            RcvDispenseBP bp = new RcvDispenseBP();
            bp.RcvLine = line1.ID;
            bp.RcvLineDispenseDTOs = dtos;
            List<RcvlineDispenseResultDTO> rcvlineDispenseResultDTOs = bp.Do();

        }

        /// <summary>
        /// RcvDispenseBP 内部代码逻辑
        /// 因为6.5不支持RcvDispenseBP,将BP内容直接放入该方法
        /// </summary>
        /// <param name="linedto"></param>
        /// <param name="doc"></param>
        /// <exception cref="Exception"></exception>
        public static void RcvDispenseEx(CopyOfOBARcvLineDTOData linedto, Receivement doc)
        {
            //不存在分发行,退出
            if (linedto.RcvLineDispenses == null || linedto.RcvLineDispenses.Count == 0)
                return;
            //依据DTO行号,获取实体行
            RcvLine rcvLine = null;
            foreach (var line in doc.RcvLines)
            {
                if (line.DocLineNo == linedto.DocLineNo)
                {
                    rcvLine = line;
                    break;
                }
            }
            if (rcvLine == null) throw new Exception("收货分发,依据行号获取行失败!");

            using (ISession session = Session.Open())
            {
                //创建收货分发行
                int rowno = 0;
                foreach (var dtodata in linedto.RcvLineDispenses)
                {
                    RcvLineDispense rcvLineDispense = RcvLineDispense.Create(rcvLine);
                    rowno += 10;
                    //部门/人员
                    if (dtodata.UseDept == null) throw new Exception("分发 UseDept 必填");
                    rcvLineDispense.UseDept = EntityUtils.GetEntityByCode<Department>(dtodata.UseDept.Code);//领用部门
                    if (dtodata.UseMan != null)
                    {
                        rcvLineDispense.UseMan = EntityUtils.GetEntityByCode<Operators>(dtodata.UseMan.Code);//领用人
                    }
                    //数量 金额
                    rcvLineDispense.DispenseQtyTU = dtodata.DispenseQtyTU;//分发数量1
                    decimal UsedMnyTC = rcvLine.FinallyPriceTC * dtodata.DispenseQtyTU;//含税领用额
                    rcvLineDispense.UsedMnyTC = EntityUtils.GetRoundMny(doc.TC, UsedMnyTC);//精度
                    decimal NetUsedMnyTC = UsedMnyTC / (1 + rcvLine.TaxRate);//未税领用额
                    rcvLineDispense.NetUsedMnyTC = EntityUtils.GetRoundMny(doc.TC, NetUsedMnyTC);//精度
                    rcvLineDispense.UsedTaxTC = UsedMnyTC - NetUsedMnyTC;//领用税额
                    rcvLineDispense.NetFeeTC = 0;//未税应摊费用额
                    rcvLineDispense.FeeTC = 0;//含税应摊费用额
                    rcvLineDispense.FeeTaxTC = 0;//应摊费用税额
                    //描述性弹性域
                    if(dtodata.DescFlexSegments != null)
                    {
                        rcvLineDispense.DescFlexSegments = new UFIDA.U9.Base.FlexField.DescFlexField.DescFlexSegments();
                        DTOUtils.DTOPropCopy(dtodata, rcvLineDispense.DescFlexSegments);
                    }
                    //其它
                    rcvLineDispense.CurrentOrg = rcvLine.CurrentOrg;//组织
                    rcvLineDispense.DispenseLineNo = rowno;//行号
                    rcvLineDispense.Grade = GradeEnum.Empty;//料品等级
                    rcvLineDispense.Potency = ElementEnum.Empty;//料品成分
                }

                session.Commit();
            }
        }

        public static void DeleteDoc(Receivement doc)
        {
            if (doc == null) return;

            //调用产业链服务
            UFIDA.U9.ISV.RCV.DeleteRCVSRV sv = new UFIDA.U9.ISV.RCV.DeleteRCVSRV();
            sv.RCVKeyList=new List<Receivement.EntityKey>() { doc.Key };
            sv.Do();

            //清除缓存
            //U9Utils.ClearCache(doc.Key);
        }

        public static Receivement UnApproveDoc(Receivement doc)
        {
            //U9Utils.ClearCache(doc.Key);
            doc = doc.Key.GetEntity();

            ApproveRCVSRV sv = new ApproveRCVSRV();
            sv.RCVLogicKeyINFOs = new List<RCVLogicKeyINFO> { new RCVLogicKeyINFO() { RcvID = doc.Key } };
            sv.ActType = ActivateTypeEnum.UnApprovedAct;
            sv.Do();

            //U9Utils.ClearCache(doc.Key);
            doc = doc.Key.GetEntity();
            //doc = Receivement.Finder.FindByID(doc.ID);
            return doc;
        }

        public static Receivement CommitDoc(Receivement doc)
        {
            using(ISession session = Session.Open())
            {
                doc.Status = RcvStatusEnum.Approving;
                foreach(var line in doc.RcvLines)
                {
                    line.Status = RcvStatusEnum.Approving;
                }

                session.Commit();
            }

            return doc;
        }

        public static Receivement ApproveDocEx(DocDTOData dto, Receivement doc)
        {
            if (!String.IsNullOrEmpty(dto.DocDate))
            {
                //修改日期
                using (ISession session = Session.Open())
                {
                    doc.BusinessDate = DateTime.Parse(dto.DocDate);//单据日期
                    doc.PostPeriod = EntityUtils.getPostPeriod(doc.BusinessDate);//记账期间
                    if (doc.SOBPostPeriod != null && doc.SOBPostPeriod.Count > 0)
                    {
                        //记账期间信息
                        doc.SOBPostPeriod[0].PostPeriod = doc.PostPeriod;
                    }
                    foreach(var line in doc.RcvLines)
                    {
                        line.ArrivedTime = doc.BusinessDate;//到货时间 
                        line.ConfirmDate = doc.BusinessDate;//入库确认日
                    }

                    session.Commit();
                }
            }
            return ApproveDoc(doc);
        }
        /// <summary>
        /// 收货单审核
        /// </summary>
        /// <param name="doc">收货单实体</param>
        /// <returns>收货单实体</returns>
        public static Receivement ApproveDoc(Receivement doc)
        {
            if (doc.Status == RcvStatusEnum.Closed)
                throw new Exception($"单号:[{doc.DocNo}]状态为业务关闭");

            doc = doc.Key.GetEntity();
            if(doc.Status== RcvStatusEnum.Opened)
            {
                CommitDoc(doc);
                doc = doc.Key.GetEntity();
            }

            //调用产业链服务审核
            ApproveRCVSRV sv = new ApproveRCVSRV();
            sv.RCVLogicKeyINFOs = new List<RCVLogicKeyINFO> { new RCVLogicKeyINFO() { RcvID=doc.Key } };
            sv.ActType = ActivateTypeEnum.ApprovedAct;
            sv.Do();

            return doc;
        }
        /// <summary>
        /// 创建收货单
        /// </summary>
        /// <param name="dto">DTO数据</param>
        /// <returns>收货单实体</returns>
        public static Receivement CreateDoc(CopyOfOBAReceivementDTOData dto)
        {
            Receivement doc;
            using (ISession se = Session.Open())
            {
                doc = Receivement.Create();
                CreateHead(doc, dto);
                CreatePostPeriod(doc, dto);
                CreateLine(doc, dto);
                CreateRcvTax(doc, dto);
    
                se.Commit();
            }

            //保存后处理
            //固定资产分发
            foreach(var linedto in dto.RcvLines)
            {
                if (linedto.RcvLineDispenses != null && linedto.RcvLineDispenses.Count > 0)
                {
                    RCVBase.RcvDispenseEx(linedto, doc);
                }
            }

            return doc;
        }
        /// <summary>
        /// 来源收货单,退货处理
        /// </summary>
        /// <param name="line"></param>
        /// <param name="linedto"></param>
        /// <exception cref="Exception"></exception>
        private static void fromRcvLine(RcvLine line, CopyOfOBARcvLineDTOData linedto)
        {
            if (line.SrcDoc == null) throw new Exception("SrcDoc不能为空");

            //来源收货单的退货处理
            String path = $"DocLineNo={linedto.SrcDoc.SrcDocLineNo} " +
                $"and Receivement.DocNo='{linedto.SrcDoc.SrcDocNo}'";
            RcvLine srcline = EntityUtils.GetEntityByPath<RcvLine>(path);
            if (srcline == null)
                throw new Exception($"查找收货单行失败,PATH:{path}");
            Receivement srcdoc = srcline.Receivement;

            Receivement doc = line.Receivement;
            //来源单据处理
            line.SrcPO = srcline.SrcPO;
            line.SrcSysVersion = srcline.Receivement.SysVersion;
            line.SrcDoc = new UFIDA.U9.CBO.SCM.PropertyTypes.SrcDocInfo
            {
                SrcDocVer = (int)srcline.Receivement.SysVersion,
                SrcDocTransTypeName = srcline.Receivement.DocType.Name,
                SrcDocTransType = new UFIDA.U9.Base.PropertyTypes.BizEntityKey
                {
                    EntityType = srcline.Receivement.DocType.GetType().FullName,
                    EntityID = srcline.Receivement.DocType.ID,
                },
                SrcDocOrg = srcline.Receivement.Org,
                SrcDocNo = srcline.Receivement.DocNo,
                SrcDocLineNo = srcline.DocLineNo,
                SrcDocLine = new UFIDA.U9.Base.PropertyTypes.BizEntityKey
                {
                    EntityType = srcline.GetType().FullName,
                    EntityID = srcline.ID,
                },
                SrcDocDate = srcline.Receivement.BusinessDate,
                SrcDocBusiType = srcline.Receivement.BizType,
                SrcDoc = new UFIDA.U9.Base.PropertyTypes.BizEntityKey
                {
                    EntityType = srcline.Receivement.GetType().FullName,
                    EntityID = srcline.Receivement.ID,
                }
            };
            //料品
            if (srcline.ItemInfo.ItemCode != linedto.ItemInfo.ItemCode)
                throw new Exception($"来源物料[{srcline.ItemInfo.ItemCode}]与传入物料[{linedto.ItemInfo.ItemCode}]不同");
            line.ItemInfo = srcline.ItemInfo;

            //其他
            doc.IsTCFromSrc = true;
            doc.IsACFromSrc = true;
            doc.TC = srcdoc.TC;
            doc.AC = srcdoc.AC;
            doc.FC = srcdoc.FC;
            line.AssociatedParentLine = srcline.ID;
            line.SrcBudgetOrg = Context.LoginOrg.ID;
            line.SrcBudgetLine = srcline.ID;
            line.SrcBudgetDocType = srcline.GetType().FullName;
            line.ConfirmAccording = srcline.ConfirmAccording;
            line.PriceSource = PriceSourceEnum.SourceDoc;
            line.Project = srcline.Project;//项目
            line.InvLot= srcline.InvLot;//批号
            line.InvLotCode = srcline.InvLotCode;
            line.INVLotInfo = srcline.INVLotInfo;
            line.InvLotEnableDate = srcline.InvLotEnableDate;
            line.InvLotValidDate = srcline.InvLotValidDate;
            line.IsPresent = srcline.IsPresent;//赠品
        }
        /// <summary>
        /// 来源采购订单处理
        /// </summary>
        /// <param name="line"></param>
        /// <param name="linedto"></param>
        /// <exception cref="Exception"></exception>
        private static void fromPOLine(RcvLine line, CopyOfOBARcvLineDTOData linedto)
        {
            if (line.SrcDoc == null) throw new Exception("SrcDoc不能为空");

            //来源=采购订单,采购收货/委外收货
            int srcSubLine = 10;
            if (linedto.SrcDoc.SrcDocSubLineNo > 0) srcSubLine = linedto.SrcDoc.SrcDocSubLineNo;
            String path = $"SubLineNo={srcSubLine} " +
                $"and POLine.DocLineNo={linedto.SrcDoc.SrcDocLineNo} " +
                $"and POLine.PurchaseOrder.DocNo='{linedto.SrcDoc.SrcDocNo}'";
            POShipLine srcline = EntityUtils.GetEntityByPath<POShipLine>(path);
            if (srcline == null)
                throw new Exception($"查找采购订单计划行失败,PATH:{path}");

            Receivement doc = line.Receivement;
            //来源单据
            PurchaseOrder po = srcline.POLine.PurchaseOrder;
            POLine poline = srcline.POLine;
            line.SrcSysVersion = srcline.SysVersion;
            line.SrcDoc = new UFIDA.U9.CBO.SCM.PropertyTypes.SrcDocInfo
            {
                //单头
                SrcDocVer = po.Version,
                SrcDocTransTypeName = po.DocType.Name,
                SrcDocTransType = new UFIDA.U9.Base.PropertyTypes.BizEntityKey
                {
                    EntityType = po.DocType.GetType().FullName,
                    EntityID = po.DocType.ID,
                },
                SrcDocOrg = po.Org,
                SrcDocNo = po.DocNo,
                SrcDocDate = po.BusinessDate,
                SrcDocBusiType = po.BizType,
                SrcDoc = new UFIDA.U9.Base.PropertyTypes.BizEntityKey
                {
                    EntityType = po.GetType().FullName,
                    EntityID = po.ID,
                },
                //单体
                SrcDocLineNo = poline.DocLineNo,
                SrcDocLine = new UFIDA.U9.Base.PropertyTypes.BizEntityKey
                {
                    EntityType = poline.GetType().FullName,
                    EntityID = poline.ID,
                },
                //孙行
                SrcDocSubLineNo = srcline.SubLineNo,
                SrcDocSubLineNoStr = srcline.SubLineNo.ToString(),
                SrcDocSubLine = new UFIDA.U9.Base.PropertyTypes.BizEntityKey
                {
                    EntityType = srcline.GetType().FullName,
                    EntityID = srcline.ID,
                }
            };
            line.SrcPO = line.SrcDoc;

            //料品
            if (srcline.ItemInfo.ItemCode != linedto.ItemInfo.ItemCode)
                throw new Exception($"来源物料[{srcline.ItemInfo.ItemCode}]与传入物料[{linedto.ItemInfo.ItemCode}]不同");
            //这里只是比对来源料号,ItemInfo在Default方法中已经创建且处理等级/成分
            //line.ItemInfo = srcline.ItemInfo;
            //if (linedto.ItemInfo.ItemGrade >= 0)
            //{
            //    line.ItemInfo.ItemGrade = GradeEnum.GetFromValue(linedto.ItemInfo.ItemGrade);//等级
            //}
            //if (linedto.ItemInfo.ItemPotency >= 0)
            //{
            //    line.ItemInfo.ItemPotency = ElementEnum.GetFromValue(linedto.ItemInfo.ItemGrade);//成分
            //}

            //其他
            doc.IsTCFromSrc = true;
            doc.IsACFromSrc = true;
            doc.TC = po.TC;
            doc.AC = po.AC;
            doc.FC = po.FC;
            line.SrcBudgetOrg = Context.LoginOrg.ID;//替代组织
            line.SrcBudgetLine = srcline.ID;//替代线索
            line.SrcBudgetDocType = srcline.GetType().FullName;//替代单据类型
            //line.ConfirmAccording =  //立账依据,来源单据/单据类型/供应商中未找到该属性
            line.PriceSource = PriceSourceEnum.SourceDoc;
            if (line.Project==null && poline.Project != null)
            {
                line.Project = poline.Project;
            }
            line.RequireDept = po.PurDept;
            line.RequireMan = po.PurOper;
            line.QuantityType = UFIDA.U9.CBO.Enums.UsageQuantityTypeEnum.Variable;
            line.BOMUOM = poline.BOMUOM;
            line.BOMID = poline.BomID;
            line.ConfirmTerm = poline.ConfirmTerm;//立账条件
            line.IsPresent = poline.IsPresent;//赠品
        }

        private static void fromASNLine(RcvLine line, CopyOfOBARcvLineDTOData linedto)
        {
            //查找ASN来源
            String path = $"DocLineNo={linedto.SrcASN.SrcDocLineNo} " +
                $"and ASN.DocNo='{linedto.SrcASN.SrcDocNo}'";
            ASNLine asnLine = ASNLine.Finder.Find(path);
            if (asnLine == null)
                throw new Exception($"查找ASN行失败,PATH:{path}");

            line.RcvLineExt = RcvLineExt.Create(line);
            //加入Session,设置保存属性
            line.RcvLineExt.SysState = UFSoft.UBF.PL.Engine.ObjectState.Inserted;
            line.RcvLineExt.NeedPersistable = true;
            line.RcvLineExt.RcvLineKey = line.Key;
            Session.Current.InList(line.RcvLineExt);

            line.RcvLineExt.SrcASNInfo = new UFIDA.U9.CBO.SCM.PropertyTypes.SrcDocInfo();
            line.RcvLineExt.SrcASNInfo.SrcDoc = new UFIDA.U9.Base.PropertyTypes.BizEntityKey();
            line.RcvLineExt.SrcASNInfo.SrcDocNo = asnLine.ASN.DocNo;
            line.RcvLineExt.SrcASNInfo.SrcDoc.EntityID = asnLine.ASNKey.ID;
            line.RcvLineExt.SrcASNInfo.SrcDoc.EntityType = asnLine.ASNKey.EntityType;

            line.RcvLineExt.SrcASNInfo.SrcDocLineNo = asnLine.DocLineNo;
            line.RcvLineExt.SrcASNInfo.SrcDocLine = new UFIDA.U9.Base.PropertyTypes.BizEntityKey();
            line.RcvLineExt.SrcASNInfo.SrcDocLine.EntityID = asnLine.Key.ID;
            line.RcvLineExt.SrcASNInfo.SrcDocLine.EntityType = asnLine.Key.EntityType;

            linedto.SrcDoc = new CopyOfSrcDocInfoData();
            linedto.SrcDoc.SrcDocNo = asnLine.SrcDocInfo.SrcDocNo;
            linedto.SrcDoc.SrcDocLineNo = asnLine.SrcDocInfo.SrcDocLineNo;
            linedto.SrcDoc.SrcDocSubLineNo = asnLine.SrcDocInfo.SrcDocSubLineNo;
        }

        
        

        private static void CreateLine(Receivement doc, CopyOfOBAReceivementDTOData dto)
        {
            foreach (var linedto in dto.RcvLines)
            {
                //数据处理
                RcvLine line = RcvLine.Create(doc);
                //默认值处理
                LineDefault(line, linedto);
                //来源单据处理
                LineSrcDoc(line, linedto);
                //数量单位处理
                LineQty(line, linedto);
                //单价金额处理
                LineMny(line, linedto);
            }
        }

        private static void LineSrcDoc(RcvLine line, CopyOfOBARcvLineDTOData linedto)
        {
            //IsASN 来源ASN,后面会执行来源=采购订单
            if (linedto.SrcASN != null)
            {
                fromASNLine(line, linedto);
            }
            //来源类型
            //CreateManual 手工创建    0   
            //PO  采购订单    1   
            //Rcv 收货单 5   
            if (line.SrcDocType == RcvSrcDocTypeEnum.CreateManual)
            {
                //手工创建
            }
            else if (line.SrcDocType == RcvSrcDocTypeEnum.Rcv)
            {
                //来源收货单
                fromRcvLine(line, linedto);
            }
            else if (line.SrcDocType == RcvSrcDocTypeEnum.PO)
            {
                //来源采购订单
                fromPOLine(line, linedto);
            }
        }

        /// <summary>
        /// 税组合处理
        /// </summary>
        /// <param name="line"></param>
        /// <param name="linedto"></param>
        /// <exception cref="Exception"></exception>
        private static void LineTaxSchedule(RcvLine line, CopyOfOBARcvLineDTOData linedto)
        {
            Receivement doc = line.Receivement;
            ItemMaster item = line.ItemInfo.ItemID;

            if (line.TaxSchedule == null)
            {
                if (linedto.TaxSchedule != null)
                {
                    //优先传入
                    line.TaxSchedule = EntityUtils.GetEntityByCode<TaxSchedule>(linedto.TaxSchedule.Code);
                }
                else if (doc.TaxSchedule != null)
                {
                    //其次单头
                    line.TaxSchedule = doc.TaxSchedule;
                }
                else if (item.PurchaseInfo.PurchaseTaxSchedule != null)
                {
                    //其次料品
                    line.TaxSchedule = item.PurchaseInfo.PurchaseTaxSchedule;
                }
            }
            if (line.SrcDocType == RcvSrcDocTypeEnum.Empty || line.SrcDocType == RcvSrcDocTypeEnum.CreateManual)
            {
                if (line.TaxSchedule == null) throw new Exception("TaxSchedule为空");
                line.TaxRate = EntityUtils.GetTaxRate(line.TaxSchedule);//税率
            }
        }
        /// <summary>
        /// 行金额计算
        /// </summary>
        /// <param name="line"></param>
        private static void LineMoneyCal(RcvLine line)
        {
            Receivement doc = line.Receivement;

            //含税金额=单价*数量(计价单位)
            line.TotalMnyTC = line.FinallyPriceTC * line.RcvQtyPU;//实收价税合计(原币)
            line.TotalMnyTC = EntityUtils.GetRoundMny(doc.TC, line.TotalMnyTC);//精度
            line.TotalMnyAC = line.FinallyPriceAC * line.RcvQtyPU;//实收价税合计(核币)
            line.TotalMnyAC = EntityUtils.GetRoundMny(doc.AC, line.TotalMnyAC);//精度
            line.TotalMnyFC = line.TotalMnyAC;//本币

            line.ArriveTotalMnyTC = line.TotalMnyTC;//实到价税合计
            line.ArriveTotalMnyAC = line.TotalMnyAC;
            line.ArriveTotalMnyFC = line.TotalMnyFC;
            

            line.RtnDeductMnyTC = line.FinallyPriceTC * line.RtnDeductQtyPU;//退扣金额
            line.RtnDeductMnyTC = U9Utils.GetRoundMoney(doc.TC, line.RtnDeductMnyTC);
            line.RtnDeductMnyAC = line.FinallyPriceAC * line.RtnDeductQtyPU;//退扣金额
            line.RtnDeductMnyAC = U9Utils.GetRoundMoney(doc.AC, line.RtnDeductMnyAC);
            line.RtnDeductMnyFC = line.RtnDeductMnyAC;

            line.RejectMnyTC = line.FinallyPriceTC * line.RejectQtyPU;//拒收金额
            line.RejectMnyTC = U9Utils.GetRoundMoney(doc.TC, line.RejectMnyTC);
            line.RejectMnyAC = line.FinallyPriceAC * line.RejectQtyPU;
            line.RejectMnyAC = U9Utils.GetRoundMoney(doc.TC, line.RejectMnyAC);
            line.RejectMnyFC = line.RejectMnyAC;
            
            //未税金额
            line.TotalNetMnyTC = line.TotalMnyTC / (1 + line.TaxRate);//实收未税额
            line.TotalNetMnyTC = EntityUtils.GetRoundMny(doc.TC, line.TotalNetMnyTC);//精度
            line.TotalNetMnyAC = line.TotalMnyAC / (1 + line.TaxRate);//实收未税额
            line.TotalNetMnyAC = EntityUtils.GetRoundMny(doc.AC, line.TotalNetMnyAC);//精度
            line.TotalNetMnyFC = line.TotalNetMnyAC;

            line.ArriveTotalNetMnyTC = line.TotalNetMnyTC;//实到未税额
            line.ArriveTotalNetMnyAC = line.TotalNetMnyAC;
            line.ArriveTotalNetMnyFC = line.TotalNetMnyFC;

            line.RtnDeductNetMnyTC = line.RtnDeductMnyTC / (1 + line.TaxRate);//未税退扣金额
            line.RtnDeductNetMnyTC = U9Utils.GetRoundMoney(doc.TC, line.RtnDeductNetMnyTC);
            line.RtnDeductNetMnyAC = line.RtnDeductMnyAC / (1 + line.TaxRate);//未税退扣金额
            line.RtnDeductNetMnyAC = U9Utils.GetRoundMoney(doc.AC, line.RtnDeductNetMnyAC);
            line.RtnDeductNetMnyFC = line.RtnDeductNetMnyAC;

            line.RejectNetMnyTC = line.RejectMnyTC / (1 + line.TaxRate);//未税拒收金额
            line.RejectNetMnyTC = U9Utils.GetRoundMoney(doc.TC, line.RejectNetMnyTC);
            line.RejectNetMnyAC = line.RejectMnyAC / (1 + line.TaxRate);//未税拒收金额
            line.RejectNetMnyAC = U9Utils.GetRoundMoney(doc.AC, line.RejectNetMnyAC);
            line.RejectNetMnyFC = line.RejectNetMnyAC;

            if (line.TotalNetMnyTC > 0)
            {
                line.EvaluationMnyTC = line.TotalNetMnyTC;//估价金额
                line.EvaluationMnyAC = line.TotalNetMnyAC;
                line.EvaluationMnyFC = line.TotalNetMnyFC;
                
            }
            if (line.RejectNetMnyTC > 0)
            {
                line.EvaluationMnyTC = line.RejectNetMnyTC;//估价金额
                line.EvaluationMnyAC = line.RejectNetMnyAC;
                line.EvaluationMnyFC = line.RejectNetMnyFC;
                
            }

            //税额
            line.TotalTaxTC = line.TotalMnyTC - line.TotalNetMnyTC;//实收税额
            line.TotalTaxAC = line.TotalMnyAC - line.TotalNetMnyAC;
            line.TotalTaxFC = line.TotalMnyFC - line.TotalNetMnyFC;
            
            line.ArriveTotalTaxTC = line.TotalTaxTC;//实到税额
            line.ArriveTotalTaxAC = line.TotalTaxAC;
            line.ArriveTotalTaxFC = line.TotalTaxFC;

            line.RtnDeductTaxTC = line.RtnDeductMnyTC - line.RtnDeductNetMnyTC;//退扣税额
            line.RtnDeductTaxAC = line.RtnDeductMnyAC - line.RtnDeductNetMnyAC;
            line.RtnDeductTaxFC = line.RtnDeductMnyFC - line.RtnDeductNetMnyFC;
            line.RejectTaxMnyTC = line.RejectMnyTC - line.RejectNetMnyTC;//拒收税额
            line.RejectTaxMnyAC = line.RejectMnyAC - line.RejectNetMnyAC;
            line.RejectTaxMnyFC = line.RejectMnyFC - line.RejectNetMnyFC;

            //未税单价
            line.NetOrderPrice = line.FinallyPriceTC / (1 + line.TaxRate);
            line.NetOrderPrice = EntityUtils.GetRoundPrice(doc.TC, line.NetOrderPrice);//精度
            line.EvaluationPricePU = line.NetOrderPrice;//计价单位
            line.EvaluationPriceCU = line.NetOrderPrice;//成本单位

        }
        /// <summary>
        /// 单价/金额/税额/税组合
        /// </summary>
        /// <param name="line"></param>
        /// <param name="linedto"></param>
        /// <exception cref="Exception"></exception>
        private static void LineMny(RcvLine line, CopyOfOBARcvLineDTOData linedto)
        {
            if (line.IsPresent == true) return;
            //来源处理
            if (line.SrcDocType == RcvSrcDocTypeEnum.CreateManual)
            {
                //手工创建
                LineTaxSchedule(line, linedto);//税组合
                //含税单价
                if (linedto.FinallyPriceTC == 0) throw new Exception("FinallyPriceTC必填");
                line.FinallyPriceTC = linedto.FinallyPriceTC;//最终价
                line.FinallyPriceAC = linedto.FinallyPriceTC;//最终价
            }
            else if (line.SrcDocType == RcvSrcDocTypeEnum.Rcv)
            {
                //来源收货单
                RcvLine srcline = RcvLine.Finder.FindByID(line.SrcDoc.SrcDocLine.EntityID);
                if (srcline == null) throw new Exception("查找来源单据失败!");
                //税组合
                line.TaxSchedule = srcline.TaxSchedule;
                if (line.TaxSchedule == null) throw new Exception("TaxSchedule为空");
                line.TaxRate = EntityUtils.GetTaxRate(line.TaxSchedule);
                //含税单价
                line.FinallyPriceTC = srcline.FinallyPriceTC;//最终价
                line.FinallyPriceAC = srcline.FinallyPriceAC;//最终价
            }
            else if (line.SrcDocType == RcvSrcDocTypeEnum.PO)
            {
                //来源采购订单
                POShipLine srcline = POShipLine.Finder.FindByID(line.SrcDoc.SrcDocSubLine.EntityID);
                if (srcline == null) throw new Exception("查找来源单据失败!");
                POLine poline = srcline.POLine;
                //税组合
                line.TaxSchedule = poline.TaxSchedule;
                if (line.TaxSchedule == null) throw new Exception("TaxSchedule为空");
                line.TaxRate = EntityUtils.GetTaxRate(line.TaxSchedule);
                //含税单价
                line.FinallyPriceTC = poline.FinallyPriceTC;//最终价
                line.FinallyPriceAC = poline.FinallyPriceAC;//最终价
                line.SrcFinallyPriceTC = line.FinallyPriceTC;//来源单据最终价
                line.SrcFinallyPriceAC = line.FinallyPriceAC;
            }
            //单价
            line.OrderPriceTC = line.FinallyPriceTC;//定价
            line.OrderPriceAC = line.FinallyPriceAC;
            line.SysPriceTC = line.FinallyPriceTC;//系统价
            line.SysPriceAC = line.FinallyPriceAC;

            //金额计算
            LineMoneyCal(line);
            //费用处理
            LineFees(line); 
        }

        private static void LineFees(RcvLine line)
        {
            if (line.SrcDocType == RcvSrcDocTypeEnum.PO)
            {
                //来源采购订单
                POShipLine sLine = POShipLine.Finder.FindByID(line.SrcDoc.SrcDocSubLine.EntityID);
                if (sLine == null) throw new Exception("查找来源单据失败!");
                POLine poline = sLine.POLine;
                if (sLine.POFees != null && sLine.POFees.Count > 0)
                {
                    int rowno = 0;
                    foreach(var poFee in sLine.POFees)
                    {
                        rowno += 10;
                        RcvFee rcvFee = RcvFee.Create(line);

                        rcvFee.FeeLineNo = rowno;
                        rcvFee.FeeC = poFee.FeeCurrency; //费用币种
                        rcvFee.FeeType = poFee.FeeType; //费用项目

                        decimal pricetc = poFee.FeeIncludeTaxTC / sLine.PlanArriveQtyTU;
                        decimal priceac = poFee.FeeIncludeTaxAC / sLine.PlanArriveQtyTU;
                        decimal pricefc = poFee.FeeIncludeTaxFC / sLine.PlanArriveQtyTU;
                        decimal pricefeec = poFee.FeeIncludeTaxFeeC / sLine.PlanArriveQtyTU;

                        rcvFee.FeeAmountTC = U9Utils.GetRoundMoney(rcvFee.FeeC, pricetc * line.RcvQtyTU); //含税费用(原币)
                        rcvFee.FeeAmountAC = U9Utils.GetRoundMoney(rcvFee.FeeC, priceac * line.RcvQtyTU); //含税费用(核币)
                        rcvFee.FeeAmountFC = U9Utils.GetRoundMoney(rcvFee.FeeC, pricefc * line.RcvQtyTU); //含税费用(本币)
                        rcvFee.FeeAmountFeeC = U9Utils.GetRoundMoney(rcvFee.FeeC, pricefeec * line.RcvQtyTU); //含税费用(费币)

                        pricetc = poFee.FeeWithOutTaxTC / sLine.PlanArriveQtyTU;
                        priceac = poFee.FeeWithOutTaxAC / sLine.PlanArriveQtyTU;
                        pricefc = poFee.FeeWithOutTaxFC / sLine.PlanArriveQtyTU;
                        pricefeec = poFee.FeeWithOutTaxFeeC / sLine.PlanArriveQtyTU;

                        rcvFee.NetFeeTC = U9Utils.GetRoundMoney(rcvFee.FeeC, pricetc * line.RcvQtyTU); //未税费用(原币)
                        rcvFee.NetFeeAC = U9Utils.GetRoundMoney(rcvFee.FeeC, priceac * line.RcvQtyTU); //未税费用(核币)
                        rcvFee.NetFeeFC = U9Utils.GetRoundMoney(rcvFee.FeeC, pricefc * line.RcvQtyTU); //未税费用(本币)
                        rcvFee.NetFeeFeeC= U9Utils.GetRoundMoney(rcvFee.FeeC, pricefeec * line.RcvQtyTU);//未税费用(费币)

                        rcvFee.FeeTaxTC = rcvFee.FeeAmountTC- rcvFee.NetFeeTC;//费用税额
                        rcvFee.FeeTaxAC = rcvFee.FeeAmountAC - rcvFee.NetFeeAC;
                        rcvFee.FeeTaxFC = rcvFee.FeeAmountFC - rcvFee.NetFeeFC;
                        rcvFee.FeeTaxFeeC = rcvFee.FeeAmountFeeC - rcvFee.NetFeeFeeC;

                        //转化率
                        rcvFee.FeeCToTCRate = poFee.FeeCToTCExchRate;
                        rcvFee.FeeCToFCRate = poFee.FeeCToFCExchRate;
                        rcvFee.FeeCToACRate = poFee.FeeCurToACRate;

                    }
                }
            }
        }

        private static void LineQty(RcvLine line, CopyOfOBARcvLineDTOData linedto)
        {
            Receivement doc = line.Receivement;
            ItemMaster item = line.ItemInfo.ItemID;

            //单位处理
            line.StoreUOM = item.InventoryUOM;//库存单位
            line.StoreBaseUOM = item.InventoryUOM.BaseUOM;
            line.TradeUOM = item.PurchaseUOM;//交易单位
            line.TradeBaseUOM = item.PurchaseUOM.BaseUOM;
            line.PriceUOM = item.PriceUOM;//计价单位
            line.PriceBaseUOM = item.PriceUOM.BaseUOM;
            line.CostUOM = item.CostUOM;//成本单位
            line.CostBaseUOM = item.CostUOM.BaseUOM;
            line.WeightUom = item.WeightUom;
            line.VolumeUom = item.BulkUom;
            if (line.SrcDocType == RcvSrcDocTypeEnum.PO)
            {
                //来源采购订单
                POShipLine srcline = POShipLine.Finder.FindByID(line.SrcDoc.SrcDocSubLine.EntityID);
                line.TradeUOM = srcline.TradeUOM;
                line.TradeBaseUOM= srcline.TradeBaseUOM;
                line.PriceUOM = srcline.PriceUOM;
                line.PriceBaseUOM= srcline.PriceBaseUOM;
                line.CostUOM= srcline.CostUOM;
                line.CostBaseUOM= srcline.CostBaseUOM;
            }

            //数量处理
            if (line.SrcDocType == RcvSrcDocTypeEnum.CreateManual || line.SrcDocType == RcvSrcDocTypeEnum.PO)
            {
                //手工创建/来源PO
                if (linedto.RcvQtyTU == 0) throw new Exception("RcvQtyTU必填");
                line.RcvQtyTU = linedto.RcvQtyTU;//实收数量(交易单位)
                if (line.SrcDocType == RcvSrcDocTypeEnum.PO)
                {
                    //来源采购订单
                    POShipLine srcline = POShipLine.Finder.FindByID(line.SrcDoc.SrcDocSubLine.EntityID);
                    line.PlanQtyTU = srcline.PlanArriveQtyTU;
                    line.PlanQtySU = srcline.PlanArriveQtySU;
                    line.PlanQtyPU = srcline.PlanArriveQtyPU;
                    line.PlanQtyCU = srcline.PlanArriveQtyCU;
                    line.PlanArrivedDate = srcline.PlanArriveDate;

                    //双单位处理
                    //使用 采购订单转换率计算计价单位
                    if (srcline.PlanArriveQtyTU != srcline.PlanArriveQtyPU)
                    {
                        line.TBUToPBURate = srcline.PlanArriveQtyPU / srcline.PlanArriveQtyTU;
                        line.RcvQtyPU = line.TBUToPBURate * line.RcvQtyTU;
                        line.RcvQtyPU = EntityUtils.GetRoundNum(line.ItemInfo.ItemID.PriceUOM, line.RcvQtyPU);//精度
                    }
                }

                if (linedto.RcvQtyPU > 0)
                {
                    //传入计价数量,重新计算转换率
                    line.RcvQtyPU = linedto.RcvQtyPU;//实收数量(计价单位)
                }
                else if (line.RcvQtyPU == 0)
                {
                    line.RcvQtyPU = line.RcvQtyTU;//实收数量(计价单位)
                }
                if (linedto.RcvQtySU > 0)
                {
                    line.RcvQtySU = linedto.RcvQtySU;//实收数量(库存单位)
                }
                else
                {
                    line.RcvQtySU = line.RcvQtyTU;//实收数量(库存单位)
                }
                if (linedto.RcvQtyCU > 0)
                {
                    line.RcvQtyCU = linedto.RcvQtyCU;//实收数量(成本单位)
                }
                else
                {
                    line.RcvQtyCU = line.RcvQtyPU;//实收数量(成本单位)
                }

                if (line.PlanQtyTU == 0)
                {
                    line.PlanQtyTU = line.RcvQtyTU;//计划到货数量
                    line.PlanQtySU = line.RcvQtySU;
                    line.PlanQtyPU = line.RcvQtyPU;
                    line.PlanQtyCU = line.RcvQtyCU;
                }
                line.EyeballingQtyTU = line.RcvQtyTU;//点收数量
                line.EyeballingQtySU = line.RcvQtySU;
                line.EyeballingQtyPU = line.RcvQtyPU;
                line.EyeballingQtyCU = line.RcvQtyCU;
                line.CanAPConfirmQtyTU = line.RcvQtyTU;//可立账数量
                line.CanAPConfirmQtySU = line.RcvQtySU;
                line.CanAPConfirmQtyPU = line.RcvQtyPU;
                line.CanAPConfirmQtyCU = line.RcvQtyCU;
                line.ArriveQtyTU = line.RcvQtyTU;//实到数量
                line.ArriveQtySU = line.RcvQtySU;
                line.ArriveQtyPU = line.RcvQtyPU;
                line.ArriveQtyCU = line.RcvQtyCU;
                line.QualifiedQtyTU = line.RcvQtyTU;//合格数量
                line.QualifiedQtySU = line.RcvQtySU;
                line.QualifiedQtyPU = line.RcvQtyPU;
                line.QualifiedQtyCU = line.RcvQtyCU;

                //转换率
                line.TBUToPBURate = line.RcvQtyPU / line.RcvQtyTU;//采购-计价
                line.TBUToCBURate = line.RcvQtyCU / line.RcvQtySU;//库存-成本
                line.TBUToSBURate = line.RcvQtySU / line.RcvQtyTU;//采购-库存

            }
            else if (line.SrcDocType == RcvSrcDocTypeEnum.Rcv)
            {
                //来源收货单
                if (linedto.RtnDeductQtyTU > 0)
                {
                    line.RtnDeductQtyTU = linedto.RtnDeductQtyTU;//退扣数量(交易)
                }
                if (linedto.RtnDeductQtyPU > 0)
                {
                    line.RtnDeductQtyPU = linedto.RtnDeductQtyPU;//退扣数量(计价)

                }
                else
                {
                    line.RtnDeductQtyPU = line.RtnDeductQtyTU;
                }
                if (linedto.RtnDeductQtySU > 0)
                {
                    line.RtnDeductQtySU = linedto.RtnDeductQtySU;//退扣数量(库存)
                }
                else
                {
                    line.RtnDeductQtySU = line.RtnDeductQtyTU;
                }
                if (linedto.RtnDeductQtyCU > 0)
                {
                    line.RtnDeductQtyCU = linedto.RtnDeductQtyCU;//退扣数量(成本)
                }
                else
                {
                    line.RtnDeductQtyCU = line.RtnDeductQtyPU;
                }
                

                if (linedto.RtnFillQtyTU > 0)
                {
                    line.RtnFillQtyTU = linedto.RtnFillQtyTU;//退补数量(交易)
                }
                if (linedto.RtnFillQtyPU > 0)
                {
                    line.RtnFillQtyPU = linedto.RtnFillQtyPU;//退补数量(计价)
                }
                else
                {
                    line.RtnFillQtyPU = line.RtnFillQtyTU;//退补数量(计价)
                }
                if (linedto.RtnFillQtySU > 0)
                {
                    line.RtnFillQtySU = linedto.RtnFillQtySU;//退补数量(库存)
                }
                else
                {
                    line.RtnFillQtySU = line.RtnFillQtyTU;//退补数量(库存)
                }
                if (linedto.RtnFillQtyCU > 0)
                {
                    line.RtnFillQtyCU=linedto.RtnFillQtyCU;//退补数量(成本)
                }
                else
                {
                    line.RtnFillQtyCU = line.RtnFillQtyPU;//退补数量(成本)
                }
                line.RejectQtyTU = line.RtnDeductQtyTU + line.RtnFillQtyTU;//拒收数量(交易)
                line.RejectQtySU = line.RtnDeductQtySU + line.RtnFillQtySU;//拒收数量(库存)
                line.RejectQtyPU = line.RtnDeductQtyPU + line.RtnFillQtyPU;//拒收数量(计价)
                line.RejectQtyCU = line.RtnDeductQtyCU + line.RtnFillQtyCU;//拒收数量(成本)
                //转化率
                line.TBUToPBURate = line.RejectQtyPU / line.RejectQtyTU;//采购-计价
                line.TBUToCBURate = line.RejectQtyCU / line.RejectQtySU;//库存-成本
                line.TBUToSBURate = line.RejectQtySU / line.RejectQtyTU;//采购-库存
            }
        }

        private static void LineDefault(RcvLine line, CopyOfOBARcvLineDTOData linedto)
        {
            Receivement doc = line.Receivement;

            if (linedto.DocLineNo > 0)
            {
                line.DocLineNo = linedto.DocLineNo;
            }
            else
            {
                line.DocLineNo = doc.RcvLines.Count*10;
                linedto.DocLineNo = line.DocLineNo;
            }
            line.SrcDocType = doc.SrcDocType;
            //组织
            line.RequireOrg = doc.Org;
            line.PurOrg = doc.Org;
            line.OwnOrg = doc.Org;
            line.CurrentOrg = doc.Org;
            line.AccountOrg = doc.Org;
            line.ConfigResultOrg = doc.Org;

            //料品
            if (String.IsNullOrEmpty(linedto.ItemInfo?.ItemCode))
                throw new Exception("必须传入物料[ItemInfo]");
            ItemMaster item = EntityUtils.GetEntityByCode<ItemMaster>(linedto.ItemInfo.ItemCode);
            line.ItemInfo = new ItemInfo()
            {
                ItemID = item,
                ItemCode = item.Code,
                ItemName = item.Name,
            };
            //等级
            if(linedto.ItemInfo.ItemGrade>0)
                line.ItemInfo.ItemGrade= GradeEnum.GetFromValue(linedto.ItemInfo.ItemGrade);
            //成分
            if (linedto.ItemInfo.ItemPotency > 0)
                line.ItemInfo.ItemPotency = ElementEnum.GetFromValue(linedto.ItemInfo.ItemPotency);

            //供应商处理
            Supplier supplier = doc.Supplier.Supplier;
            if (supplier.SupplierSites != null && supplier.SupplierSites.Count > 0)
            {
                line.ShipToSite = new SupplierSiteMISCInfo
                {
                    SupplierSite = supplier.SupplierSites[0],
                    Code = supplier.SupplierSites[0].Code,
                    Name = supplier.SupplierSites[0].Name,
                };
                line.BillToSite = line.ShipToSite;
            }
            line.PayerSite = doc.PayerSite;
            line.Payer = doc.Payer;

            //转换率
            line.TUToTBURate = 1;
            line.TCToACExchRate = 1;
            line.TBUToSBURate = 1;
            line.TBUToPBURate = 1;
            line.TBUToCBURate = 1;
            line.SUToSBURate = 1;
            line.PUToPBURate = 1;
            line.CUToCBURate = 1;
            line.ACToFCExchRate = 1;

            //扩展字段处理
            if (linedto.DescFlexSegments != null)
            {
                line.DescFlexSegments = new UFIDA.U9.Base.FlexField.DescFlexField.DescFlexSegments();
                DTOUtils.DTOPropCopy(linedto.DescFlexSegments, line.DescFlexSegments);
            }

            //批次处理
            if (!String.IsNullOrEmpty(linedto.InvLotCode))
            {
                //不用查询主档,BE会自动创建主档
                line.InvLotCode = linedto.InvLotCode;
                if (!String.IsNullOrEmpty(linedto.InvLotEnableDate))
                {
                    line.InvLotEnableDate = DateTime.Parse(linedto.InvLotEnableDate);
                    line.InvLotValidDate = line.InvLotValidDate;
                }

            }

            //其他
            line.IsPresent = linedto.IsPresent;//赠品
            if (linedto.Project?.Code != null)
            {
                line.Project = EntityUtils.GetEntityByCode<Project>(linedto.Project.Code);
            }

            line.RcvDept = EntityUtils.GetEntityByCode<Department>(linedto.RcvDept);//收货部门
            line.WhMan = EntityUtils.GetEntityByCode<Operators>(linedto.WhMan);//库管员
            if (line.WhMan != null)
            {
                line.RcvDept = line.WhMan.Dept;
            }

            line.Wh = EntityUtils.GetEntityByCode<Warehouse>(linedto.Wh);//存储地点
            line.StorageType = UFIDA.U9.CBO.Enums.StorageTypeEnum.Useable;//存储类型

            line.PurOper = EntityUtils.GetEntityByCode<Operators>(linedto.PurOper);
            line.PurDept = line.RcvDept;
            line.RcvBy = supplier.ReceiptRule;
            line.PreMaturityDate = doc.BusinessDate;
            line.PostPeriod = doc.PostPeriod;
            line.PaymentTerm = doc.PaymentTerm;
            line.MatchLayer = UFIDA.U9.CBO.FI.MatchLayerSet.MatchGradeEnum.Way4;
            line.IsTCToACRateFromSrc = true;
            line.IsPriceIncludeTax = true;
            line.IsRcvProcedureModify = true;
            line.IsEditSeiBan = true;
            line.IsAdjustDosagePerPiece = true;
            line.IsEvaluationChangeable = true;
            line.MaxPrepayPercentEditable = true;
            line.IsEditMfc = true;

            line.ConfirmTerm = supplier.APConfirmTerm;//立账条件
            line.ConfirmSupplier = doc.Supplier;
            line.ConfirmDate = doc.BusinessDate;
            line.ArrivedTime = doc.BusinessDate;
            line.StateMachineID = Guid.Empty;

            //line.ConfirmAccording =  //立账依据,单据类型/供应商中未找到该属性
            line.QuantityType = UFIDA.U9.CBO.Enums.UsageQuantityTypeEnum.Variable;//数量类型=变动
            doc.IsTCFromSrc = false;
            doc.IsACFromSrc = false;
            line.IsTCToACRateFromSrc = false;
            line.RejectMode = doc.RejectMode;
            line.PlanArrivedDate = DateTime.Now;
            line.EyeballedTime = DateTime.Now;
            line.PriceSource = PriceSourceEnum.Custom;//价格来源=手工
        }

        /// <summary>
        /// 资产卡片回写收货单
        /// </summary>
        /// <param name="disline">收货单分发行</param>
        /// <param name="qty">建卡数量</param>
        public static void CardUpdateRcv(RcvLineDispense disline,int qty)
        {
            if (disline == null) return;

            using(ISession session = Session.Open())
            {
                RcvLine line = disline.RcvLine;

                line.ActivateType = ActivateTypeEnum.SVUpdate;//当前活动
                disline.SetupCardQtyTU += qty;//建卡数量
                disline.CanProcessQtyTU -= qty;//可处理数量

                //收货单税明细
                RCVBase.CreateDisTax(disline, qty);

                session.Commit();
            }
        }

        /// <summary>
        /// 创建分发行税子表
        /// 问题:未考虑建卡数量
        /// </summary>
        /// <param name="disline">收货单分发行</param>
        /// <param name="qty">建卡数量</param>
        private static void CreateDisTax(RcvLineDispense disline, int qty)
        {
            //避免重复创建
            if (disline.RcvTaxs != null && disline.RcvTaxs.Count > 0)
                return;

            //创建税子行
            RcvLine line = disline.RcvLine;
            RcvTax tax = RcvTax.Create(disline);
            if (line.TaxSchedule.TaxScheduleTaxs != null && line.TaxSchedule.TaxScheduleTaxs.Count > 0)
            {
                tax.TaxType = line.TaxSchedule.TaxScheduleTaxs[0].Tax;//税别
                tax.TaxRate = line.TaxSchedule.TaxScheduleTaxs[0].Tax.TaxRate;//税率
            }
            tax.TaxLineNo = 1;
            tax.CurrentOrg = disline.CurrentOrg;
            tax.TaxMnyType = TaxMnyTypeEnum.UsedTax;//税额类型
            tax.TaxMnyTC = disline.UsedTaxTC;//税额（交易币）
            tax.TaxMnyAC = disline.UsedTaxTC;//税额（核币）
            tax.TaxMnyFC = disline.UsedTaxTC;//税额（本币）
        }
        /// <summary>
        /// 收货行税子表创建
        /// </summary>
        /// <param name="doc"></param>
        /// <param name="dto"></param>
        private static void CreateRcvTax(Receivement doc, CopyOfOBAReceivementDTOData dto)
        {
            foreach (var line in doc.RcvLines)
            {
                //赠品不处理税子表
                if (line.IsPresent) continue;

                if (line.RtnDeductTaxTC > 0)
                {
                    //创建退货扣款税额
                    RcvTax tax = RcvTax.Create(line);
                    if (line.TaxSchedule.TaxScheduleTaxs != null && line.TaxSchedule.TaxScheduleTaxs.Count > 0)
                    {
                        tax.TaxType = line.TaxSchedule.TaxScheduleTaxs[0].Tax;
                        tax.TaxRate = line.TaxSchedule.TaxScheduleTaxs[0].Tax.TaxRate;

                    }
                    tax.TaxLineNo = 1;
                    tax.RcvLine = line;
                    tax.CurrentOrg = line.CurrentOrg;

                    tax.TaxMnyType = TaxMnyTypeEnum.RtnDeductTax;//0-退货扣款税额
                    tax.TaxMnyTC = line.RtnDeductTaxTC;
                    tax.TaxMnyAC = line.RtnDeductTaxTC;
                    tax.TaxMnyFC = line.RtnDeductTaxTC;
                }

                if (line.RejectTaxMnyTC > 0)
                {
                    //创建拒收税额
                    RcvTax tax = RcvTax.Create(line);
                    if (line.TaxSchedule.TaxScheduleTaxs != null && line.TaxSchedule.TaxScheduleTaxs.Count > 0)
                    {
                        tax.TaxType = line.TaxSchedule.TaxScheduleTaxs[0].Tax;
                        tax.TaxRate = line.TaxSchedule.TaxScheduleTaxs[0].Tax.TaxRate;

                    }
                    tax.TaxLineNo = 1;
                    tax.RcvLine = line;
                    tax.CurrentOrg = line.CurrentOrg;

                    tax.TaxMnyType = TaxMnyTypeEnum.RejectTax;//4-拒收税额
                    tax.TaxMnyTC = line.RejectTaxMnyTC;
                    tax.TaxMnyAC = line.RejectTaxMnyAC;
                    tax.TaxMnyFC = line.RejectTaxMnyFC;
                }

                //改为>=0,因为零税率也要生成税子表
                if (line.TotalTaxTC >= 0)
                {
                    //创建实到税额
                    RcvTax tax = UFIDA.U9.PM.Rcv.RcvTax.Create(line);
                    if (line.TaxSchedule.TaxScheduleTaxs != null && line.TaxSchedule.TaxScheduleTaxs.Count > 0)
                    {
                        tax.TaxType = line.TaxSchedule.TaxScheduleTaxs[0].Tax;
                        tax.TaxRate = line.TaxSchedule.TaxScheduleTaxs[0].Tax.TaxRate;
                    }
                    tax.TaxLineNo = 1;
                    tax.RcvLine = line;
                    tax.CurrentOrg = line.CurrentOrg;

                    tax.TaxMnyType = TaxMnyTypeEnum.ArriveTax;//2-实到税额
                    tax.TaxMnyTC = line.TotalTaxTC;
                    tax.TaxMnyAC = line.TotalTaxTC;
                    tax.TaxMnyFC = line.TotalTaxTC;

                    //创建实收税额
                    RcvTax tax1 = UFIDA.U9.PM.Rcv.RcvTax.Create(line);
                    if (line.TaxSchedule.TaxScheduleTaxs != null && line.TaxSchedule.TaxScheduleTaxs.Count > 0)
                    {
                        tax1.TaxType = line.TaxSchedule.TaxScheduleTaxs[0].Tax;
                        tax1.TaxRate = line.TaxSchedule.TaxScheduleTaxs[0].Tax.TaxRate;
                    }
                    tax1.TaxLineNo = 2;
                    tax1.RcvLine = line;
                    tax1.CurrentOrg = line.CurrentOrg;

                    tax1.TaxMnyType = TaxMnyTypeEnum.ReceiveTax;//1-实收税额
                    tax1.TaxMnyTC = line.TotalTaxTC;
                    tax1.TaxMnyAC = line.TotalTaxTC;
                    tax1.TaxMnyFC = line.TotalTaxTC;
                }
            }
        }

        private static void CreatePostPeriod(Receivement doc, CopyOfOBAReceivementDTOData dto)
        {
            SOBPostPeriod post = SOBPostPeriod.Create(doc);
            post.SOB = EntityUtils.getSetofBooks();
            post.Receivement = doc;
            post.PostPeriod = doc.PostPeriod;
            post.CurrentOrg = Context.LoginOrg;
        }

        private static void CreateHead(Receivement doc, CopyOfOBAReceivementDTOData dto)
        {
            //doc.DocNo = dto.DocNo;
            if (String.IsNullOrEmpty(dto.BusinessDate))
            {
                throw new Exception("必须传入[BusinessDate]");
            }
            doc.BusinessDate = DateTime.Parse(dto.BusinessDate);
            doc.PostPeriod = EntityUtils.getPostPeriod(doc.BusinessDate);

            //来源类别
            doc.SrcDocType = RcvSrcDocTypeEnum.GetFromValue(dto.SrcDocType);
            if (doc.SrcDocType == RcvSrcDocTypeEnum.Empty)
                doc.SrcDocType = RcvSrcDocTypeEnum.CreateManual;//如果不传,则手工创建
            
            //单据类型处理
            if (dto.RcvDocType == null) throw new Exception("单据类型必填");
            doc.RcvDocType = EntityUtils.GetEntityByCode<RcvDocType>(dto.RcvDocType.Code);
            doc.BizType = doc.RcvDocType.BusinessType;//业务类型
            doc.RtnType = doc.RcvDocType.RtnType;//退货类型
            doc.RejectMode = RejectModeEnum.GetFromValue(1);//拒收处理方式=创建补货单追踪
            doc.ReceivementType = doc.RcvDocType.ReceivementType;//收货单类型

            //供应商处理
            Supplier supplier = EntityUtils.GetEntityByCode<Supplier>(dto.Supplier.Code);
            doc.Supplier = new SupplierMISCInfo()
            {
                Supplier = supplier,
                ShortName = supplier.ShortName,
                Name = supplier.Name,
                Code = supplier.Code,
            };
            doc.Payer = doc.Supplier;
            if (supplier.SupplierSites != null && supplier.SupplierSites.Count > 0)
            {
                doc.PayerSite = new SupplierSiteMISCInfo()
                {
                    SupplierSite = supplier.SupplierSites[0],
                    Name = supplier.SupplierSites[0].Name,
                    Code = supplier.SupplierSites[0].Code,
                };
            }
            doc.RcvBy = supplier.ReceiptRule;
            doc.ConfirmTerm = supplier.APConfirmTerm;
            doc.PaymentTerm = supplier.PaymentTerm;

            //币种
            doc.TC = EntityUtils.GetEntityByCode<Currency>("C001");
            doc.AC = doc.TC;
            doc.FC = doc.TC;

            //税组合,税率
            if (dto.TaxSchedule != null)
            {
                //优先传入
                doc.TaxSchedule = EntityUtils.GetEntityByCode<TaxSchedule>(dto.TaxSchedule.Code);
            }
            else if (supplier.TaxSchedule != null)
            {
                //其次供应商
                doc.TaxSchedule = supplier.TaxSchedule;
            }
            if (doc.TaxSchedule != null)
            {
                doc.TaxRate = supplier.TaxSchedule.TaxScheduleTaxs[0].Tax.TaxRate;
            }

            //组织
            doc.Org = Context.LoginOrg;
            doc.PurOrg = Context.LoginOrg;
            doc.BalanceOrg = Context.LoginOrg;
            doc.AccountOrg = Context.LoginOrg;

            
            //扩展字段处理
            if (dto.DescFlexField != null)
            {
                doc.DescFlexField = new UFIDA.U9.Base.FlexField.DescFlexField.DescFlexSegments();
                DTOUtils.DTOPropCopy(dto.DescFlexField, doc.DescFlexField);
            }

            //其他
            doc.TCToACExRate = 1;
            doc.ACToFCExRate = 1;
            doc.IsTCFromSrc = true;
            doc.IsPriceIncludeTax = true;
            doc.IsExchRateType = true;
            doc.IsACFromSrc = true;
            doc.IsPaymentTermChangeable = true;
            doc.IsConfirmTermChangeable = true;
            doc.IsRcvByChangeable = true;
            doc.IsPriceListChangeable = true;

            doc.WorkFlowID=Guid.Empty;
            doc.StateMachineID=Guid.Empty;
        }
    }
}
